"""
SQL语法分析器 V2.0
完全符合实践要求：支持CREATE TABLE、INSERT、SELECT、DELETE四种语句
"""

import ply.yacc as yacc
from .lexer_v2 import SQLLexerV2

class SQLParserV2:
    """SQL语法分析器 V2.0"""
    
    def __init__(self):
        """初始化语法分析器"""
        self.lexer = SQLLexerV2()
        self.tokens = self.lexer.tokens
        self.parser = yacc.yacc(module=self, debug=False)
        self.ast = None
    
    # 语法规则定义
    def p_statement(self, p):
        """statement : create_statement
                     | insert_statement
                     | select_statement
                     | delete_statement
                     | update_statement"""
        p[0] = p[1]
    
    # CREATE TABLE语句
    def p_create_statement(self, p):
        """create_statement : CREATE TABLE IDENTIFIER LPAREN column_list RPAREN SEMICOLON"""
        p[0] = {
            'type': 'CREATE_TABLE',
            'table_name': p[3],
            'columns': p[5]
        }
    
    def p_column_list(self, p):
        """column_list : column_list COMMA column_def
                       | column_def"""
        if len(p) == 4:
            p[0] = p[1] + [p[3]]
        else:
            p[0] = [p[1]]
    
    def p_column_def(self, p):
        """column_def : IDENTIFIER data_type
                      | IDENTIFIER data_type PRIMARY KEY"""
        column_def = {
            'name': p[1],
            'type': p[2]
        }
        if len(p) == 5:  # 有PRIMARY KEY
            column_def['primary_key'] = True
        p[0] = column_def
    
    def p_data_type(self, p):
        """data_type : INT
                     | VARCHAR LPAREN NUMBER RPAREN
                     | FLOAT
                     | BOOLEAN"""
        if len(p) == 2:
            p[0] = {'type': p[1].lower()}
        else:  # VARCHAR(n)
            p[0] = {'type': 'varchar', 'length': p[3]}
    
    # INSERT语句
    def p_insert_statement(self, p):
        """insert_statement : INSERT INTO IDENTIFIER VALUES LPAREN value_list RPAREN SEMICOLON"""
        p[0] = {
            'type': 'INSERT',
            'table_name': p[3],
            'values': p[6]
        }
    
    def p_value_list(self, p):
        """value_list : value_list COMMA value
                      | value"""
        if len(p) == 4:
            p[0] = p[1] + [p[3]]
        else:
            p[0] = [p[1]]
    
    def p_value(self, p):
        """value : NUMBER
                 | STRING
                 | NULL"""
        p[0] = p[1]
    
    # SELECT语句
    def p_select_statement(self, p):
        """select_statement : SELECT select_list FROM IDENTIFIER where_clause SEMICOLON"""
        p[0] = {
            'type': 'SELECT',
            'columns': p[2],
            'table_name': p[4],
            'where': p[5]
        }
    
    def p_select_list(self, p):
        """select_list : select_list COMMA column_reference
                       | column_reference
                       | TIMES"""
        if len(p) == 2 and p[1] == '*':
            p[0] = '*'
        elif len(p) == 4:
            p[0] = p[1] + [p[3]]
        else:
            p[0] = [p[1]]
    
    def p_column_reference(self, p):
        """column_reference : IDENTIFIER
                            | IDENTIFIER DOT IDENTIFIER"""
        if len(p) == 2:
            p[0] = p[1]
        else:
            p[0] = f"{p[1]}.{p[3]}"
    
    def p_where_clause(self, p):
        """where_clause : WHERE condition
                        | empty"""
        p[0] = p[1] if len(p) > 1 else None
    
    def p_condition(self, p):
        """condition : condition AND condition
                     | condition OR condition
                     | NOT condition
                     | expression comparison_op expression
                     | LPAREN condition RPAREN"""
        if len(p) == 4:
            if p[1] == '(':
                p[0] = p[2]
            else:
                p[0] = {
                    'type': p[2],
                    'left': p[1],
                    'right': p[3]
                }
        elif len(p) == 3:
            p[0] = {
                'type': p[1],
                'operand': p[2]
            }
        else:
            p[0] = {
                'type': p[2],
                'left': p[1],
                'right': p[3]
            }
    
    def p_comparison_op(self, p):
        """comparison_op : EQ
                         | NE
                         | LT
                         | LE
                         | GT
                         | GE"""
        p[0] = p[1]
    
    def p_expression(self, p):
        """expression : expression PLUS expression
                      | expression MINUS expression
                      | expression TIMES expression
                      | expression DIVIDE expression
                      | column_reference
                      | value
                      | LPAREN expression RPAREN"""
        if len(p) == 4:
            if p[1] == '(':
                p[0] = p[2]
            else:
                p[0] = {
                    'type': 'binary_op',
                    'operator': p[2],
                    'left': p[1],
                    'right': p[3]
                }
        else:
            p[0] = p[1]
    
    # UPDATE语句
    def p_update_statement(self, p):
        """update_statement : UPDATE IDENTIFIER SET assignment_list where_clause SEMICOLON"""
        p[0] = {
            'type': 'UPDATE',
            'table_name': p[2],
            'assignments': p[4],
            'where': p[5]
        }
    
    def p_assignment_list(self, p):
        """assignment_list : assignment_list COMMA assignment
                           | assignment"""
        if len(p) == 4:
            p[0] = p[1] + [p[3]]
        else:
            p[0] = [p[1]]
    
    def p_assignment(self, p):
        """assignment : IDENTIFIER EQ value"""
        p[0] = {
            'column': p[1],
            'value': p[3]
        }
    
    # DELETE语句
    def p_delete_statement(self, p):
        """delete_statement : DELETE FROM IDENTIFIER where_clause SEMICOLON"""
        p[0] = {
            'type': 'DELETE',
            'table_name': p[3],
            'where': p[4]
        }
    
    # 空产生式
    def p_empty(self, p):
        """empty :"""
        pass
    
    # 错误处理
    def p_error(self, p):
        if p:
            print(f"语法错误: 在 '{p.value}' 附近，位置 ({p.lineno}, {p.lexpos})")
            print(f"期望的符号: 可能是关键字、标识符或操作符")
        else:
            print("语法错误: 意外的文件结束")
    
    def parse(self, text):
        """解析SQL语句，返回AST"""
        try:
            self.ast = self.parser.parse(text, lexer=self.lexer.lexer)
            return self.ast
        except Exception as e:
            print(f"解析错误: {str(e)}")
            return None
    
    def print_ast(self, node=None, indent=0):
        """打印AST"""
        if node is None:
            node = self.ast
        
        if isinstance(node, dict):
            for key, value in node.items():
                if isinstance(value, (dict, list)):
                    print("  " * indent + f"{key}:")
                    if isinstance(value, list):
                        for i, item in enumerate(value):
                            print("  " * (indent + 1) + f"[{i}]:")
                            self.print_ast(item, indent + 2)
                    else:
                        self.print_ast(value, indent + 1)
                else:
                    print("  " * indent + f"{key}: {value}")
        else:
            print("  " * indent + str(node))
    
    def test(self, text):
        """测试语法分析器"""
        print(f"输入SQL: {text}")
        print("-" * 50)
        
        # 词法分析
        print("1. 词法分析:")
        tokens = self.lexer.tokenize(text)
        self.lexer.print_tokens()
        
        # 语法分析
        print("\n2. 语法分析:")
        ast = self.parse(text)
        if ast:
            print("AST构建成功:")
            self.print_ast(ast)
        else:
            print("AST构建失败")
        
        return ast

# 测试函数
if __name__ == "__main__":
    parser = SQLParserV2()
    
    # 测试用例
    test_cases = [
        "CREATE TABLE student(id INT, name VARCHAR(50), age INT);",
        "INSERT INTO student VALUES (1, 'Alice', 20);",
        "SELECT id, name FROM student WHERE age > 18;",
        "DELETE FROM student WHERE id = 1;"
    ]
    
    for test_case in test_cases:
        print("\n" + "="*60)
        parser.test(test_case)
